{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "268e010c",
   "metadata": {},
   "source": [
    "# 本周目标\n",
    ">函数的定义  \n",
    ">函数的使用  \n",
    ">函数的参数  \n",
    "# 函数的定义\n",
    "> 定义一个函数的一般步骤"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "3ad0212e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 1 2 3 5 8 \n"
     ]
    }
   ],
   "source": [
    "a, b = 0, 1\n",
    "while a < 10:\n",
    "    print(a, end=' ')\n",
    "    a, b = b, a+b\n",
    "print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "a5ab610b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# .....避免重复使用一个功能\n",
    "# .....只要调用函数即可function_name（）"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73dc06ea",
   "metadata": {},
   "source": [
    "* 1.定义函数的一般方法：\n",
    "```\n",
    "def function_name(): # 1.function_name遵循变量定义的规则\n",
    "    \"\"\"函数的注释\"\"\"# 2.函数的注释可以和使用者交流\n",
    "    函数体          # 3，函数体要与定义函数保持一定的tab缩进\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "12222227",
   "metadata": {},
   "outputs": [],
   "source": [
    "def fib(n):  # 写一个斐波那契数列\n",
    "    \"\"\"Print a Fibonacci series up to n.\"\"\"\n",
    "    a, b = 0, 1\n",
    "    while a < n:\n",
    "        print(a, end=' ')\n",
    "        a, b = b, a + b\n",
    "    print()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "ac90e983",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 1 2 3 5 8 13 21 34 55 \n"
     ]
    }
   ],
   "source": [
    "fib(60)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "cdb8f5c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def hello():\n",
    "    \"\"\"打印你好世界\"\"\"\n",
    "    print(\"hello world\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "40553f85",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello world\n"
     ]
    }
   ],
   "source": [
    "hello()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "4e51d6e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def hello_user(username):\n",
    "    \"\"\"打印你好+使用者\"\"\"\n",
    "    print(\"hello！\"+username.title()+\"同学\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "f21fdb9e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello！Jack同学\n"
     ]
    }
   ],
   "source": [
    "hello_user(\"jack\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ca4c577",
   "metadata": {},
   "source": [
    "* 思考：函数是否必须有参数？\n",
    "* 注意：\n",
    "    >1.在第一行定义函数中，不需要任何信息就能完成工作，因此括号是空的（即便如此，括号必不可少！）  \n",
    "    >2.要调用函数，可以依次指定函数名以及括号括起的必要信息。在第五行代码中，因为此函数hello()括号中不需要任何信息，只需要输入hello()即可。和预期效果一样，打印hello,world!\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5c55fb70",
   "metadata": {},
   "source": [
    "# 函数的参数\n",
    ">1.形式参数  \n",
    ">>1.定义函数时，写在 function_name 括号里面的参数  \n",
    ">>2.在定义函数时，形式参数不占用空间  \n",
    ">2.实际参数  \n",
    ">>1.调用函数时, 写在 function_name 括号里面的参数  \n",
    ">>2.在使用函数时，形式参数 被 分配空间，变为实际参数  "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf900d2e",
   "metadata": {},
   "source": [
    "* 当函数具有多个参数时\n",
    "\n",
    ">1.位置参数\n",
    ">>1.形式参数有先后顺序，函数调用过程中应考虑参数的先后顺序，避免出现顺序错误的笑话  \n",
    ">>2.调用函数过程中要考虑形式参数的个数（给少给多都报错）  \n",
    "\n",
    ">2.关键字参数  \n",
    ">>1.调用函数时，通过赋值的方式传递给定义好的形参变量数据  \n",
    ">>2.关键字参数不考虑先后顺序，因为是指定变量赋值的  \n",
    "\n",
    ">3.默认参数  \n",
    ">>1.在形式参数中，提前预设一个用户可能使用的参数值  \n",
    ">>2.用户在使用/调用函数时，可以省略不给默认参数赋值  \n",
    ">>3.用户给默认参数赋值，将替换默认参数的值  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "945a461b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def describe_pet(animal_type,pet_name):#animal_type,pet_name是形式参数   形参\n",
    "    \"\"\"显示宠物信息\"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My\" + animal_type + \"'s name is \"+pet_name.title() + \".\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "1df00631",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a cat.\n",
      "Mycat's name is 大黑.\n"
     ]
    }
   ],
   "source": [
    "# 位置参数\n",
    "describe_pet(\"cat\",\"大黑\")#\"cat\",\"大黑\"是实际参数 实参"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "647f4964",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a 大黑.\n",
      "My大黑's name is Cat.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"大黑\",\"cat\")# 函数调用过程中应考虑参数的先后顺序先写animal_type，后写pet_name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "131d2b4b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a cat.\n",
      "Mycat's name is 大黑.\n"
     ]
    }
   ],
   "source": [
    "# 关键字参数\n",
    "describe_pet(pet_name=\"大黑\",animal_type=\"cat\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "df8b0c4b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 默认参数\n",
    "def describe_pet(pet_name,animal_type=\"dog\"):#animal_type,pet_name是形式参数   形参\n",
    "    \"\"\"显示宠物信息\"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My\" + animal_type + \"'s name is \"+pet_name.title() + \".\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "393799b6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "Mydog's name is 大黑.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"大黑\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "370bf238",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a cat.\n",
      "Mycat's name is 大黑.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"大黑\",\"cat\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb04d627",
   "metadata": {},
   "source": [
    "\n",
    "参数使用过程中的思考和问题：\n",
    ">1.思考：关键字参数和位置参数是否可以一起使用？——<strong>可以一起使用</strong>\n",
    ">>1.positional argument follows keyword argument，位置函数<font style=\"color:red\">均</font>要放在关键字参数前面  \n",
    ">>2.test1() got multiple values for argument 'x'(映射，不能出现multiple values（多重值）)  \n",
    "\n",
    ">2.定义函数：默认参数和非默认参数的先后关系\n",
    ">>1.non-default argument follows default argument(非默认函数<font style=\"color:red\">均</font>要放在默认参数前面)    \n",
    "——————"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "445645cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 以下为测试代码\n",
    "#案例一\n",
    "def test1(x,y,z):\n",
    "    \"\"\"打印x,y,z的值\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "56bb5f82",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "positional argument follows keyword argument (<ipython-input-79-fd583303ea9b>, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-79-fd583303ea9b>\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m    test1(x=2,3,z=4)\u001b[0m\n\u001b[1;37m              ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m positional argument follows keyword argument\n"
     ]
    }
   ],
   "source": [
    "test1(x=2,3,z=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "7b6ea3f3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "test1(2,y=3,z=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "c7b304b7",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "positional argument follows keyword argument (<ipython-input-81-32b91fe9ca8b>, line 1)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-81-32b91fe9ca8b>\"\u001b[1;36m, line \u001b[1;32m1\u001b[0m\n\u001b[1;33m    test1(2,y=3,4)\u001b[0m\n\u001b[1;37m                ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m positional argument follows keyword argument\n"
     ]
    }
   ],
   "source": [
    "test1(2,y=3,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "293bf262",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "test1(2,z=4,y=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "42d32691",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "test1() got multiple values for argument 'x'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-83-abf767fdec53>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mtest1\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: test1() got multiple values for argument 'x'"
     ]
    }
   ],
   "source": [
    "test1(2,x=3,y=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "3b3211ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "#案例二\n",
    "def test1(x,z,y=3):#非默认函数均要放在默认参数前面\n",
    "    \"\"\"打印x,y,z的值\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ab801e2e",
   "metadata": {},
   "source": [
    "# 课本的练习实践\n",
    ">请大家总结函数的优势  \n",
    ">预习第四章的函数和模块  \n",
    ">>完成元音字母实践  \n",
    ">>浏览模块，创建模块和调用模块，了解PEP 8 python国际代码标准"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "de12f6b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "def search4vowels(word):\n",
    "    \"\"\"判断输入文本出现的元音字母有哪些\"\"\"\n",
    "    vowels = set(\"aeiou\")\n",
    "    word = set(word)\n",
    "    print(vowels & word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "172d02dc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'e', 'a'}\n"
     ]
    }
   ],
   "source": [
    "search4vowels(\"aesddwx\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "401e87b4",
   "metadata": {},
   "source": [
    "# 函数的优势"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0d880db",
   "metadata": {},
   "source": [
    "* 在本章中，学习了：如何编写函数，以及如何传递实参，让函数能够访问完成其工作所需的信息:\n",
    "> 如何使用位置实参和关键字实参，以及如何接受任意数量的实参；显示输出的函数和返回值的函数；    \n",
    "> 如何将函数同列表、字典、if语句和while循环结合起来使用；如何将函数存储在称为模块的独立文件中，让程序文件更简单、更易于理解。    \n",
    "> 最后，学习了函数编写指南，遵循这些指南可让程序始终结构良好，并对使用者来说易于阅读。    \n",
    "----------------------------------------------------------------------------------------\n",
    "* <strong>程序员的目标之一是，编写简单的代码来完成任务，而函数有助于实现这样的目标。</strong>\n",
    "* 它们让使用者<font style=color:green>在编写好代码块并确定其能够正确运行后，就可置之不理。</font>\n",
    "* 确定函数能够正确地完成其工作后，就可以接着投身于下一个编码任务。\n",
    "* 函数让使用者编写代码一次后，想重用它们多少次就重用多少次。\n",
    "* 需要运行函数中的代码时，只需编写一行函数调用代码，就可让函数完成其工作。\n",
    "* 需要<font style=color:green> 修改函数的行为时，只需修改一个代码块，而所做的修改将影响调用这个函数的每个地方。</font>\n",
    "* <font style=color:green>使用函数让程序更容易阅读，而良好的函数名概述了程序各个部分的作用。</font>\n",
    "*相对于阅读一系列的代码块，阅读一系列函数调用让使用者能够更快地明白程序的作用。\n",
    "* <font style=color:green> 函数还让代码更容易测试和调试。</font>\n",
    "* 如果程序使用一系列的函数来完成其任务，而其中的每个函数都完成一项具体的工作，测试和维护起来将容易得多：\n",
    "* 可编写分别调用每个函数的程序，并测试每个函数是否在它可能遇到的各种情形下都能正确地运行。\n",
    "* 经过这样的测试后你就能充满信心，深信每次调用这些函数时，它们都将正确地运行。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2db52e1c",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
